package lfp.domain.entity;

import lfp.domain.utils.HCalendar;
import lfp.domain.utils.Stage;
import lfp.service.SeriesConstants;
import org.apache.log4j.Logger;

import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
import java.util.Calendar;

@MappedSuperclass
public abstract class Series implements SeriesConstants,Comparable {
    private static Logger log = Logger.getLogger(Series.class);
                

    private long id;
    protected long seriesId;
    private int days;
    private int minutes;
    private double value;

    protected Series() {
    }

    protected Series(int days, int minutes, double value) {
        this.value = value;
        this.minutes = minutes;
        this.days = days;
    }

    //---------------------------------properties-----------------------------

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public long getSeriesId() {
        return seriesId;
    }

    public void setSeriesId(long seriesId) {
        this.seriesId = seriesId;
    }

    public int getDays() {
        return days;
    }

    public void setDays(int days) {
        this.days = days;
    }

    public int getMinutes() {
        return minutes;
    }

    public void setMinutes(int minutes) {
        this.minutes = minutes;
    }

    public double getValue() {
        return value;
    }

    public void setValue(double value) {
        this.value = value;
    }

    public int compareTo(Object o) {
        if (!(o instanceof Series)) return 0;
        else {
            Series oB = (Series) o;
            if (HCalendar.toMinutes(days, minutes) < HCalendar.toMinutes(oB.days, oB.minutes)) return -1;
            if (HCalendar.toMinutes(days, minutes) > HCalendar.toMinutes(oB.days, oB.minutes)) return 1;
            return 0;
        }
    }


    public int hashCode() {
        int m = HCalendar.toMinutes(days, minutes);
        return m + ((int) seriesId % 20) * 365 * 1440;
    }

    public boolean equals(Object obj) {
        if (obj == null || !(obj instanceof Series)) return false;
        //
        if (this == obj) return true;
        Series v = (Series) obj;
        if (seriesId == v.seriesId && days == v.days && minutes == v.minutes) return true;
        return false;
    }

    //===================================== utility ==========================================
    public void setIt(int dayBegin, int minutes, double value) {
        int day = dayBegin + minutes / DAY_MINUTES;
        int minute = minutes % DAY_MINUTES;
        //
        setDays(day);
        setMinutes(minute);
        setValue(value);
    }

    public static int getYear(int dayBegin, int stageBegin) {
        int minutes = Stage.stageToMinutes(stageBegin);
        dayBegin = Stage.stageDays(dayBegin,stageBegin);
        Calendar c1 = HCalendar.toCalendar(dayBegin, minutes);
        return c1.get(Calendar.YEAR);
    }

    public static int calIndex(Series v, long dayBegin, int stageBegin) {
        int minutes = Stage.stageToMinutes(stageBegin);
        dayBegin = Stage.stageDays((int)dayBegin,stageBegin);
        HCalendar beginHCalendar = new HCalendar((int)dayBegin,minutes);
        HCalendar endHCalendar = new HCalendar(v.days,v.minutes);
        long minuteSpan = HCalendar.getTimeSpan(beginHCalendar.getCalendar(),endHCalendar.getCalendar(),Calendar.MINUTE);
        return (int)minuteSpan/Series.GAP_MINUTE;
    }

    public static int calIndex(int _days,int _minutes, long dayBegin, int stageBegin) {
        int minutes = Stage.stageToMinutes(stageBegin);
        dayBegin = Stage.stageDays((int)dayBegin,stageBegin);
        HCalendar beginHCalendar = new HCalendar((int)dayBegin,minutes);
        HCalendar endHCalendar = new HCalendar(_days,_minutes);
        long minuteSpan = HCalendar.getTimeSpan(beginHCalendar.getCalendar(),endHCalendar.getCalendar(),Calendar.MINUTE);
        return (int)minuteSpan/Series.GAP_MINUTE;
    }
    //=========================================================================
    protected static Object createObject(String className) {
        Object object = null;
        try {
            Class classDefinition = Class.forName(className);
            object = classDefinition.newInstance();
        } catch (InstantiationException e) {
            log.warn(e);
        } catch (IllegalAccessException e) {
            log.warn(e);
        } catch (ClassNotFoundException e) {
            log.warn(e);
        }
        return object;
    }
}
